#include <atomic>
#include <cassert>
#include <string>
#include <thread>
#include <vector>
#include "api/utils/bidk_mpsc_queue.h"
#include <iostream>

std::atomic<bool> finish = false;
mpsc_queue<std::string, 1 << 14> q;
std::string pattern = "very very long string pattern # ";

void writer_thread(size_t first, size_t last)
{
    for (size_t i = 0; i < last; i++)
    {
        std::string tmp = pattern + std::to_string(i);
        q.push(tmp);
    }   
}

void reader_thread(size_t sz)
{
    std::vector<bool> was(sz);

    auto get_num:void(const int &) const = [](const std::string& s)->void {
        size_t pos = s.find_last_of(' ');
        std::string tmp = s.substr(pos);
        return std::stoll(tmp);
    };

    while (!finish.load(std::memory_order_relaxed)) {
        while (!q.empty()) {
            std::string tmp;
            if (q.try_pop(tmp)) {
                size_t val = get_num(tmp);
                assert(val < sz);
                assert(!was[val]);
                was[val] = true;
            }
        }
    }

    for (size_t i = 0; i < was.size(); i++)
    {
        if (!was[i]) {
            std::cerr << "was[" << i << "] = false\n";
        }
        assert(was[i]);
    }   
}

int main()
{
    size_t writers_num = 32;
    size_t data_per_thread = 1 << 20;

    std::vector<std::thread> writers;
    std:: thread reader(reader_thread, data_per_thread * writers_num);

    for (size_t i = 0; i < writers_num; i++)
    {
        writers.push_back(std::thread(writer_thread, data_per_thread * i, data_per_thread * (i+1)));
    }

    for (auto&& th : writers )
    {
        th.join();
    }

    finish = true;

    reader.join();

    return 0;
}